package org.rsbot.script.methods;

import java.awt.Point;
import java.util.Random;
import org.rsbot.client.Client;
import org.rsbot.client.RSGroundData;
import org.rsbot.client.RSInterface;
import org.rsbot.client.Render;
import org.rsbot.client.RenderData;
import org.rsbot.client.TileData;
import org.rsbot.script.wrappers.RSCharacter;
import org.rsbot.script.wrappers.RSComponent;
import org.rsbot.script.wrappers.RSObject;
import org.rsbot.script.wrappers.RSTile;

public class Calculations extends MethodProvider
{
  public static final int[] SIN_TABLE = new int[16384];
  public static final int[] COS_TABLE = new int[16384];

  private final Render render = new Render();
  private final RenderData renderData = new RenderData();

  Calculations(MethodContext paramMethodContext) {
    super(paramMethodContext);
  }

  public boolean tileOnMap(RSTile paramRSTile)
  {
    return distanceTo(paramRSTile) < 15;
  }

  public boolean tileOnScreen(RSTile paramRSTile)
  {
    return pointOnScreen(tileToScreen(paramRSTile, 0.5D, 0.5D, 0));
  }

  public Point tileToMinimap(RSTile paramRSTile)
  {
    return worldToMinimap(paramRSTile.getX(), paramRSTile.getY());
  }

  public boolean pointOnScreen(Point paramPoint)
  {
    int i = paramPoint.x; int j = paramPoint.y;
    if (this.methods.game.isFixed()) {
      return (i > 4) && (i < this.methods.game.getWidth() - 253) && (j > 4) && (j < this.methods.game.getHeight() - 169);
    }

    return (i > 0) && (i < this.methods.game.getWidth() - 260) && (j > 0) && (j < this.methods.game.getHeight() - 149);
  }

  public double distanceBetween(Point paramPoint1, Point paramPoint2)
  {
    return Math.sqrt((paramPoint1.x - paramPoint2.x) * (paramPoint1.x - paramPoint2.x) + (paramPoint1.y - paramPoint2.y) * (paramPoint1.y - paramPoint2.y));
  }

  public double random(double paramDouble1, double paramDouble2)
  {
    return Math.min(paramDouble1, paramDouble2) + this.methods.random.nextDouble() * Math.abs(paramDouble2 - paramDouble1);
  }

  public RSTile getTileOnScreen(RSTile paramRSTile)
  {
    try
    {
      if (tileOnScreen(paramRSTile)) {
        return paramRSTile;
      }
      RSTile localRSTile1 = this.methods.players.getMyPlayer().getLocation();
      RSTile localRSTile2 = new RSTile((paramRSTile.getX() + localRSTile1.getX()) / 2, (paramRSTile.getY() + localRSTile1.getY()) / 2);

      if (tileOnScreen(localRSTile2)) {
        return localRSTile2;
      }
      return getTileOnScreen(localRSTile2);
    } catch (StackOverflowError localStackOverflowError) {
    }
    return null;
  }

  public int angleToTile(RSTile paramRSTile)
  {
    RSTile localRSTile = this.methods.players.getMyPlayer().getLocation();
    int i = (int)Math.toDegrees(Math.atan2(paramRSTile.getY() - localRSTile.getY(), paramRSTile.getX() - localRSTile.getX()));

    return i >= 0 ? i : 360 + i;
  }

  public Point tileToScreen(RSTile paramRSTile, double paramDouble1, double paramDouble2, int paramInt)
  {
    return groundToScreen((int)((paramRSTile.getX() - this.methods.client.getBaseX() + paramDouble1) * 512.0D), (int)((paramRSTile.getY() - this.methods.client.getBaseY() + paramDouble2) * 512.0D), paramInt);
  }

  public Point tileToScreen(RSTile paramRSTile, int paramInt)
  {
    return tileToScreen(paramRSTile, 0.5D, 0.5D, paramInt);
  }

  public Point tileToScreen(RSTile paramRSTile)
  {
    return tileToScreen(paramRSTile, 0);
  }

  public int distanceTo(RSCharacter paramRSCharacter)
  {
    return paramRSCharacter == null ? -1 : distanceTo(paramRSCharacter.getLocation());
  }

  public int distanceTo(RSObject paramRSObject)
  {
    return paramRSObject == null ? -1 : distanceTo(paramRSObject.getLocation());
  }

  public int distanceTo(RSTile paramRSTile)
  {
    return paramRSTile == null ? -1 : (int)distanceBetween(this.methods.players.getMyPlayer().getLocation(), paramRSTile);
  }

  public double distanceBetween(RSTile paramRSTile1, RSTile paramRSTile2)
  {
    return Math.sqrt((paramRSTile1.getX() - paramRSTile2.getX()) * (paramRSTile1.getX() - paramRSTile2.getX()) + (paramRSTile1.getY() - paramRSTile2.getY()) * (paramRSTile1.getY() - paramRSTile2.getY()));
  }

  public int pathLengthTo(RSTile paramRSTile, boolean paramBoolean)
  {
    RSTile localRSTile = this.methods.players.getMyPlayer().getLocation();
    return pathLengthBetween(localRSTile, paramRSTile, paramBoolean);
  }

  public int pathLengthBetween(RSTile paramRSTile1, RSTile paramRSTile2, boolean paramBoolean)
  {
    return dijkstraDist(paramRSTile1.getX() - this.methods.client.getBaseX(), paramRSTile1.getY() - this.methods.client.getBaseY(), paramRSTile2.getX() - this.methods.client.getBaseX(), paramRSTile2.getY() - this.methods.client.getBaseY(), paramBoolean);
  }

  public boolean canReach(RSTile paramRSTile, boolean paramBoolean)
  {
    return pathLengthTo(paramRSTile, paramBoolean) != -1;
  }

  public Point worldToMinimap(double paramDouble1, double paramDouble2)
  {
    if (distanceBetween(this.methods.players.getMyPlayer().getLocation(), new RSTile((int)paramDouble1, (int)paramDouble2)) > 17.0D)
    {
      return new Point(-1, -1);
    }
    paramDouble1 -= this.methods.client.getBaseX();
    paramDouble2 -= this.methods.client.getBaseY();
    int i = (int)(paramDouble1 * 4.0D + 2.0D) - this.methods.client.getMyRSPlayer().getX() / 128;

    int j = (int)(paramDouble2 * 4.0D + 2.0D) - this.methods.client.getMyRSPlayer().getY() / 128;
    try
    {
      RSInterface localRSInterface = this.methods.gui.getMinimapInterface();

      if (localRSInterface == null)
        return new Point(-1, -1);
      RSComponent localRSComponent = this.methods.interfaces.getComponent(localRSInterface.getID());

      int k = i * i + j * j;

      int m = 10 + Math.max(localRSComponent.getWidth() / 2, localRSComponent.getHeight() / 2);

      if (m * m >= k) {
        int n = 0x3FFF & (int)this.methods.client.getMinimapOffset();
        if (this.methods.client.getMinimapSetting() != 4) {
          n = 0x3FFF & this.methods.client.getMinimapAngle() + (int)this.methods.client.getMinimapOffset();
        }

        int i1 = SIN_TABLE[n];
        int i2 = COS_TABLE[n];
        if (this.methods.client.getMinimapSetting() != 4) {
          i3 = 256 + this.methods.client.getMinimapScale();
          i1 = 256 * i1 / i3;
          i2 = 256 * i2 / i3;
        }

        int i3 = i2 * i + i1 * j >> 15;
        int i4 = i2 * j - i1 * i >> 15;

        int i5 = i3 + localRSComponent.getAbsoluteX() + localRSComponent.getWidth() / 2;

        int i6 = -i4 + localRSComponent.getAbsoluteY() + localRSComponent.getHeight() / 2;

        return new Point(i5, i6);
      }
    }
    catch (NullPointerException localNullPointerException)
    {
    }

    return new Point(-1, -1);
  }

  public Point groundToScreen(int paramInt1, int paramInt2, int paramInt3)
  {
    if ((this.methods.client.getGroundByteArray() == null) || (this.methods.client.getTileData() == null) || (paramInt1 < 512) || (paramInt2 < 512) || (paramInt1 > 52224) || (paramInt2 > 52224))
    {
      return new Point(-1, -1);
    }

    int i = tileHeight(paramInt1, paramInt2) + paramInt3;

    return worldToScreen(paramInt1, paramInt2, i);
  }

  public int tileHeight(int paramInt1, int paramInt2)
  {
    int i = this.methods.client.getPlane();

    int j = paramInt1 >> 9;
    int k = paramInt2 >> 9;

    byte[][][] arrayOfByte = this.methods.client.getGroundByteArray();

    if ((arrayOfByte != null) && (j >= 0) && (j < 104) && (k >= 0) && (k < 104))
    {
      if ((i <= 3) && ((arrayOfByte[1][j][k] & 0x2) != 0)) {
        i++;
      }
      TileData[] arrayOfTileData = this.methods.client.getTileData();

      if ((arrayOfTileData != null) && (i < arrayOfTileData.length) && (arrayOfTileData[i] != null)) {
        int[][] arrayOfInt = arrayOfTileData[i].getHeights();
        if (arrayOfInt != null) {
          int m = paramInt1 & 0x1FF;
          int n = paramInt2 & 0x1FF;
          int i1 = arrayOfInt[j][k] * (512 - m) + arrayOfInt[(j + 1)][k] * m >> 9;

          int i2 = arrayOfInt[j][(1 + k)] * (512 - m) + arrayOfInt[(j + 1)][(k + 1)] * m >> 9;

          return i1 * (512 - n) + i2 * n >> 9;
        }
      }
    }

    return 0;
  }

  public Point worldToScreen(int paramInt1, int paramInt2, int paramInt3)
  {
    float f = this.renderData.zOff + (int)(this.renderData.zX * paramInt1 + this.renderData.zY * paramInt3 + this.renderData.zZ * paramInt2);

    if ((f >= this.render.zNear) && (f <= this.render.zFar)) {
      int i = (int)(this.render.xMultiplier * ((int)this.renderData.xOff + (int)(this.renderData.xX * paramInt1 + this.renderData.xY * paramInt3 + this.renderData.xZ * paramInt2)) / f);

      int j = (int)(this.render.yMultiplier * ((int)this.renderData.yOff + (int)(this.renderData.yX * paramInt1 + this.renderData.yY * paramInt3 + this.renderData.yZ * paramInt2)) / f);

      if ((i >= this.render.absoluteX1) && (i <= this.render.absoluteX2) && (j >= this.render.absoluteY1) && (j <= this.render.absoluteY2))
      {
        if (this.methods.game.isFixed()) {
          return new Point((int)(i - this.render.absoluteX1) + 4, (int)(j - this.render.absoluteY1) + 4);
        }

        int k = (int)(i - this.render.absoluteX1); int m = (int)(j - this.render.absoluteY1);
        return new Point(k, m);
      }
    }

    return new Point(-1, -1);
  }

  public void updateRenderInfo(Render paramRender, RenderData paramRenderData)
  {
    if ((paramRender == null) || (paramRenderData == null)) {
      return;
    }
    this.render.absoluteX1 = paramRender.getAbsoluteX1();
    this.render.absoluteX2 = paramRender.getAbsoluteX2();
    this.render.absoluteY1 = paramRender.getAbsoluteY1();
    this.render.absoluteY2 = paramRender.getAbsoluteY2();

    this.render.xMultiplier = paramRender.getXMultiplier();
    this.render.yMultiplier = paramRender.getYMultiplier();

    this.render.zNear = paramRender.getZNear();
    this.render.zFar = paramRender.getZFar();

    this.renderData.xOff = paramRenderData.getXOff();
    this.renderData.xX = paramRenderData.getXX();
    this.renderData.xY = paramRenderData.getXY();
    this.renderData.xZ = paramRenderData.getXZ();

    this.renderData.yOff = paramRenderData.getYOff();
    this.renderData.yX = paramRenderData.getYX();
    this.renderData.yY = paramRenderData.getYY();
    this.renderData.yZ = paramRenderData.getYZ();

    this.renderData.zOff = paramRenderData.getZOff();
    this.renderData.zX = paramRenderData.getZX();
    this.renderData.zY = paramRenderData.getZY();
    this.renderData.zZ = paramRenderData.getZZ();
  }

  private int dijkstraDist(int paramInt1, int paramInt2, int paramInt3, int paramInt4, boolean paramBoolean)
  {
    int[][] arrayOfInt1 = new int[104][104];
    int[][] arrayOfInt2 = new int[104][104];
    int[] arrayOfInt3 = new int[4000];
    int[] arrayOfInt4 = new int[4000];

    for (int i = 0; i < 104; i++) {
      for (j = 0; j < 104; j++) {
        arrayOfInt1[i][j] = 0;
        arrayOfInt2[i][j] = 99999999;
      }
    }

    i = paramInt1;
    int j = paramInt2;
    arrayOfInt1[paramInt1][paramInt2] = 99;
    arrayOfInt2[paramInt1][paramInt2] = 0;
    int k = 0;
    int m = 0;
    arrayOfInt3[k] = paramInt1;
    arrayOfInt4[(k++)] = paramInt2;
    int[][] arrayOfInt5 = this.methods.client.getRSGroundDataArray()[this.methods.game.getPlane()].getBlocks();

    int n = arrayOfInt3.length;
    int i1 = 0;
    while (m != k) {
      i = arrayOfInt3[m];
      j = arrayOfInt4[m];

      if (paramBoolean) {
        if (((i == paramInt3) && (j == paramInt4 + 1)) || ((i == paramInt3) && (j == paramInt4 - 1)) || ((i == paramInt3 + 1) && (j == paramInt4)) || ((i == paramInt3 - 1) && (j == paramInt4)))
        {
          i1 = 1;
          break;
        }

      }
      else if ((i == paramInt3) && (j == paramInt4)) {
        i1 = 1;
      }

      m = (m + 1) % n;
      int i2 = arrayOfInt2[i][j] + 1;

      if ((j > 0) && (arrayOfInt1[i][(j - 1)] == 0) && ((arrayOfInt5[(i + 1)][j] & 0x1280102) == 0))
      {
        arrayOfInt3[k] = i;
        arrayOfInt4[k] = (j - 1);
        k = (k + 1) % n;
        arrayOfInt1[i][(j - 1)] = 1;
        arrayOfInt2[i][(j - 1)] = i2;
      }

      if ((i > 0) && (arrayOfInt1[(i - 1)][j] == 0) && ((arrayOfInt5[i][(j + 1)] & 0x1280108) == 0))
      {
        arrayOfInt3[k] = (i - 1);
        arrayOfInt4[k] = j;
        k = (k + 1) % n;
        arrayOfInt1[(i - 1)][j] = 2;
        arrayOfInt2[(i - 1)][j] = i2;
      }

      if ((j < 103) && (arrayOfInt1[i][(j + 1)] == 0) && ((arrayOfInt5[(i + 1)][(j + 2)] & 0x1280120) == 0))
      {
        arrayOfInt3[k] = i;
        arrayOfInt4[k] = (j + 1);
        k = (k + 1) % n;
        arrayOfInt1[i][(j + 1)] = 4;
        arrayOfInt2[i][(j + 1)] = i2;
      }

      if ((i < 103) && (arrayOfInt1[(i + 1)][j] == 0) && ((arrayOfInt5[(i + 2)][(j + 1)] & 0x1280180) == 0))
      {
        arrayOfInt3[k] = (i + 1);
        arrayOfInt4[k] = j;
        k = (k + 1) % n;
        arrayOfInt1[(i + 1)][j] = 8;
        arrayOfInt2[(i + 1)][j] = i2;
      }

      if ((i > 0) && (j > 0) && (arrayOfInt1[(i - 1)][(j - 1)] == 0) && ((arrayOfInt5[i][j] & 0x128010E) == 0) && ((arrayOfInt5[i][(j + 1)] & 0x1280108) == 0) && ((arrayOfInt5[(i + 1)][j] & 0x1280102) == 0))
      {
        arrayOfInt3[k] = (i - 1);
        arrayOfInt4[k] = (j - 1);
        k = (k + 1) % n;
        arrayOfInt1[(i - 1)][(j - 1)] = 3;
        arrayOfInt2[(i - 1)][(j - 1)] = i2;
      }

      if ((i > 0) && (j < 103) && (arrayOfInt1[(i - 1)][(j + 1)] == 0) && ((arrayOfInt5[i][(j + 2)] & 0x1280138) == 0) && ((arrayOfInt5[i][(j + 1)] & 0x1280108) == 0) && ((arrayOfInt5[(i + 1)][(j + 2)] & 0x1280120) == 0))
      {
        arrayOfInt3[k] = (i - 1);
        arrayOfInt4[k] = (j + 1);
        k = (k + 1) % n;
        arrayOfInt1[(i - 1)][(j + 1)] = 6;
        arrayOfInt2[(i - 1)][(j + 1)] = i2;
      }

      if ((i < 103) && (j > 0) && (arrayOfInt1[(i + 1)][(j - 1)] == 0) && ((arrayOfInt5[(i + 2)][j] & 0x1280183) == 0) && ((arrayOfInt5[(i + 2)][(j + 1)] & 0x1280180) == 0) && ((arrayOfInt5[(i + 1)][j] & 0x1280102) == 0))
      {
        arrayOfInt3[k] = (i + 1);
        arrayOfInt4[k] = (j - 1);
        k = (k + 1) % n;
        arrayOfInt1[(i + 1)][(j - 1)] = 9;
        arrayOfInt2[(i + 1)][(j - 1)] = i2;
      }

      if ((i < 103) && (j < 103) && (arrayOfInt1[(i + 1)][(j + 1)] == 0) && ((arrayOfInt5[(i + 2)][(j + 2)] & 0x12801E0) == 0) && ((arrayOfInt5[(i + 2)][(j + 1)] & 0x1280180) == 0) && ((arrayOfInt5[(i + 1)][(j + 2)] & 0x1280120) == 0))
      {
        arrayOfInt3[k] = (i + 1);
        arrayOfInt4[k] = (j + 1);
        k = (k + 1) % n;
        arrayOfInt1[(i + 1)][(j + 1)] = 12;
        arrayOfInt2[(i + 1)][(j + 1)] = i2;
      }
    }
    return i1 != 0 ? arrayOfInt2[i][j] : -1;
  }

  static
  {
    for (int i = 0; i < 16384; i++) {
      SIN_TABLE[i] = (int)(32768.0D * Math.sin(i * 0.0003834951969714103D));
      COS_TABLE[i] = (int)(32768.0D * Math.cos(i * 0.0003834951969714103D));
    }
  }

  static class RenderData
  {
    float xOff = 0.0F; float xX = 32768.0F; float xY = 0.0F; float xZ = 0.0F;
    float yOff = 0.0F; float yX = 0.0F; float yY = 32768.0F; float yZ = 0.0F;
    float zOff = 0.0F; float zX = 0.0F; float zY = 0.0F; float zZ = 32768.0F;
  }

  static class Render
  {
    float absoluteX1 = 0.0F; float absoluteX2 = 0.0F;
    float absoluteY1 = 0.0F; float absoluteY2 = 0.0F;
    int xMultiplier = 512; int yMultiplier = 512;
    int zNear = 50; int zFar = 3500;
  }
}